﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http;
using System.Net;

using ERPStore.Extensions;

using CloudSoft.Extensions;

namespace ERPStore.Web.NewsLetters.Controllers
{
	public class NewsLettersApiController : ApiController
	{
		public NewsLettersApiController(ERPStore.Services.CryptoService cryptoService
			, ERPStore.NewsLetters.Services.NewsLettersService newsLettersService
			, ERPStore.Services.IAccountService accountService
			, ERPStore.NewsLetters.Models.Settings settings
			, ERPStore.NewsLetters.Services.TrackerService trackerService
			, ERPStore.Logging.ILogger logger
			, ERPStore.Services.IServiceBus serviceBus
			)
		{
			this.CryptoService = cryptoService;
			this.NewsLetterService = newsLettersService;
			this.AccountService = accountService;
			this.Settings = settings;
			this.TrackerService = trackerService;
			this.Logger = logger;
			this.ServiceBus = serviceBus;
		}

		protected ERPStore.Services.CryptoService CryptoService { get; private set; }
		protected ERPStore.NewsLetters.Services.NewsLettersService NewsLetterService { get; private set; }
		protected ERPStore.Services.IAccountService AccountService { get; private set; }
		protected ERPStore.NewsLetters.Models.Settings Settings { get; private set; }
		protected ERPStore.NewsLetters.Services.TrackerService TrackerService { get; private set; }
		protected ERPStore.Logging.ILogger Logger { get; private set; }
		protected ERPStore.Services.IServiceBus ServiceBus { get; private set; }

		[System.Web.Http.HttpGet]
		public DateTime Ping()
		{
			return DateTime.Now;
		}

		#region Campaign

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.Campaign CreateCampaign()
		{
			var campaign = NewsLetterService.CreateCampaign();
			return campaign;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.CampaignListResult GetCampaignList(ERPStore.NewsLetters.Models.CampaignListFilter filter)
		{
			int count = 0;
			var list = NewsLetterService.GetCampaignList(filter, out count);

			var idList = list.Select(i => i.Id);
			var statList = TrackerService.GetCampaignStatListByIdList(idList);

			foreach (var item in list)
			{
				var stats = statList.FirstOrDefault(i => i.CampaignStatId == item.Id);
				if (stats == null)
				{
					stats = new ERPStore.NewsLetters.Models.CampaignStat();
					stats.CampaignStatId = item.Id;
				}
				item.Stats = stats;
			}

			var result = new ERPStore.NewsLetters.Models.CampaignListResult();
			result.TotalCount = count;
			result.List.AddRange(list);
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPut]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.Campaign SaveCampaign(ERPStore.NewsLetters.Models.Campaign campaign)
		{
			var result = NewsLetterService.SaveCampaign(campaign);
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.Campaign GetCampaignById(int Id)
		{
			return NewsLetterService.GetCampaignById(Id);
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpDelete]
		[System.Web.Http.HttpPost]
		public void DeleteCampaign(int Id)
		{
			throw new NotImplementedException();
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPost]
		public List<ERPStore.Models.BrokenRule> ValidateCampaign(ERPStore.NewsLetters.Models.Campaign campaign)
		{
			var result = NewsLetterService.ValidateCampaign(campaign);
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public string ScheduleCampaign(ERPStore.NewsLetters.Models.CampaignScheduler cs)
		{
			ServiceBus.Send(ERPStore.NewsLetters.Queues.QUEUE_SCHEDULE_CAMPAIGN, new ERPStore.NewsLetters.Models.ScheduleCampaignQueueMessage()
			{
				CampaignId = cs.CampaingId,
				ScheduledDate = cs.StartDate.ToLocalTime(),
			});
			Logger.Info("Newsletter campaign {0} scheduled at {1}", cs.CampaingId, cs.StartDate);
			return null;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public void StopCampaign(int Id)
		{
			throw new NotImplementedException();
		}

		#endregion

		#region NewsLetter

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.NewsLetter CreateNewsLetter()
		{
			var newsLetter = NewsLetterService.CreateNewsLetter();
			return newsLetter;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.NewsLetterListResult GetNewsLetterList(ERPStore.NewsLetters.Models.NewsLetterListFilter filter)
		{
			int count = 0;
			var list = NewsLetterService.GetNewsLettersList(filter, out count);

			var result = new ERPStore.NewsLetters.Models.NewsLetterListResult();
			result.TotalCount = filter.TotalCount;
			result.List.AddRange(list);
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public Dictionary<int, string> GetNewsLetterDictionary()
		{
			var list = NewsLetterService.GetNewsLetterDictionary();
			return list;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPost]
		public IList<ERPStore.Models.BrokenRule> ValidateNewsLetter(ERPStore.NewsLetters.Models.NewsLetter newsLetter)
		{
			var br = NewsLetterService.ValidateNewsLetter(newsLetter);
			return br;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPut]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.NewsLetter SaveNewsLetter(ERPStore.NewsLetters.Models.NewsLetter newsLetter)
		{
			NewsLetterService.SaveNewsLetter(newsLetter);
			return newsLetter;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.NewsLetter GetNewsLetterById(int Id)
		{
			var result = NewsLetterService.GetNewsLetterById(Id);
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpDelete]
		[System.Web.Http.HttpPost]
		public bool DeleteNewsLetter(int id)
		{
			if (id == 0)
			{
				return false;
			}
			NewsLetterService.DeleteNewsLetter(id);
			return true;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public string GetNewsLetterPreviewKey(ERPStore.NewsLetters.Models.NewsLetter newsLetter)
		{
			var testEmail = ERPStore.NewsLetters.Configuration.ConfigurationSettings.AppSettings["testEmail"];
			var emailList = testEmail.Split(';').ToList();

			var trakingKey = new ERPStore.NewsLetters.Models.TrackingKey()
			{
				Email = emailList.First(),
				NewsLetterId = newsLetter.Id,
				CampaignId = -1,
				CreationDate = DateTime.Now,
				LinkName = "preview",
				UserId = -1,
			};

			var encryptedKey = CryptoService.Encrypt(trakingKey);

			return encryptedKey;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPost]
		public System.Threading.Tasks.Task<HttpResponseMessage> PostFiles()
		{
			if (!Request.Content.IsMimeMultipartContent())
			{
				var httpResponse = new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType);
				throw new HttpResponseException(httpResponse);
			}

			var result = new Dictionary<string, byte[]>();
			// var rootFolder = System.IO.Path.GetTempPath();
			// var streamProvider = new MultipartFormDataStreamProvider(rootFolder);

			int newsLetterId = 0;

			var task = Request.Content.ReadAsMultipartAsync().ContinueWith<HttpResponseMessage>(t =>
				{
					if (t.IsFaulted || t.IsCanceled)
					{
						Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
					}

					foreach (var item in t.Result.Contents)
					{
						if (item.Headers.ContentDisposition.Name.Trim('"') == "newsLetterId")
						{
							newsLetterId = Convert.ToInt32(item.ReadAsStringAsync().Result);
							continue;
						}
						var content = item.ReadAsByteArrayAsync().Result;
						var fileName = item.Headers.ContentDisposition.FileName.Trim('"');

						result.Add(fileName, content);
					}

					if (newsLetterId == 0)
					{
						return null;
					}

					var m_VirtualFilePath = ERPStore.NewsLetters.Configuration.ConfigurationSettings.AppSettings["virtualFilePath"];
					var m_PhysicalPath = ERPStore.GlobalConfiguration.Configuration.Settings.PhysicalPath;
					m_PhysicalPath = System.IO.Path.Combine(m_PhysicalPath, m_VirtualFilePath.Replace("~/", "").Replace("/", @"\"));
					m_PhysicalPath = System.IO.Path.Combine(m_PhysicalPath, string.Format(@"img\nl{0}", newsLetterId));

					if (!System.IO.Directory.Exists(m_PhysicalPath))
					{
						System.IO.Directory.CreateDirectory(m_PhysicalPath);
					}

					foreach (var item in result.Keys)
					{
						var fileName = System.IO.Path.Combine(m_PhysicalPath, item);
						if (System.IO.File.Exists(fileName))
						{
							System.IO.File.Delete(fileName);
						}
						System.IO.File.WriteAllBytes(fileName, result[item]);
					}

					return Request.CreateResponse(HttpStatusCode.OK);
					
				});

			return task;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.MediaResourceList GetResourceListByNewsLetterId(int Id)
		{
			var m_VirtualFilePath = ERPStore.NewsLetters.Configuration.ConfigurationSettings.AppSettings["virtualFilePath"];
			var physicalPath = ERPStore.GlobalConfiguration.Configuration.Settings.PhysicalPath;
			physicalPath = System.IO.Path.Combine(physicalPath, m_VirtualFilePath.Replace("~/", "").Replace("/", @"\"));

			var path = System.IO.Path.Combine(physicalPath, string.Format(@"img\nl{0}", Id));
			if (!System.IO.Directory.Exists(path))
			{
				return null;
			}
			var fileList = from file in System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.TopDirectoryOnly)
						   let fileInfo = new System.IO.FileInfo(file)
						   select new ERPStore.NewsLetters.Models.MediaResource()
						   {
							   CreationDate = fileInfo.CreationTime,
							   FileName = fileInfo.Name,
							   Url = string.Format("{0}/newsletters/images/nl{1}/{2}", ERPStore.GlobalConfiguration.Configuration.Settings.CurrentUrl, Id, fileInfo.Name),
							   Length = fileInfo.Length,
						   };

			var result = new ERPStore.NewsLetters.Models.MediaResourceList()
			{
				TotalCount = fileList.Count(),
				List = fileList.ToList(),
			};
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[HttpDelete]
		public bool DeleteResource(int newsLetterId, string fileName)
		{
			var m_VirtualFilePath = ERPStore.NewsLetters.Configuration.ConfigurationSettings.AppSettings["virtualFilePath"];
			var m_PhysicalPath = ERPStore.GlobalConfiguration.Configuration.Settings.PhysicalPath;
			m_PhysicalPath = System.IO.Path.Combine(m_PhysicalPath, m_VirtualFilePath.Replace("~/", "").Replace("/", @"\"));
			m_PhysicalPath = System.IO.Path.Combine(m_PhysicalPath, string.Format(@"img\nl{0}", newsLetterId));
			var fullFileName = System.IO.Path.Combine(m_PhysicalPath, fileName);
			if (System.IO.File.Exists(fullFileName))
			{
				try
				{
					System.IO.File.Delete(fullFileName);
				}
				catch
				{
					return false;
				}
			}
			else
			{
				return false;
			}

			return true;
		}

		#endregion

		#region Sent / Tracking

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.EmailSentListResult GetEmailSentList(ERPStore.NewsLetters.Models.EmailSentListFilter filter)
		{
			var list = NewsLetterService.GetEmailSentDetailList(filter);
			var result = new ERPStore.NewsLetters.Models.EmailSentListResult();
			result.TotalCount = filter.TotalCount;
			if (list.IsNotNullOrEmpty())
			{
				result.List.AddRange(list);
			}
			return result;
		}

		public IList<ERPStore.NewsLetters.Models.Track> GetLastTrackList(int campaignId, int count)
		{
			var list = TrackerService.GetLastOpenedEmail(campaignId, count);
			return list;
		}

		public int GetTrackCount(int campaignId)
		{
			return TrackerService.GetTrackCount(campaignId);
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		public Dictionary<string, int> GetCampaignClickStatByLink(int id)
		{
			var result = TrackerService.GetCampaignClickStatByLink(id);
			return result;
		}

		#endregion

		#region SMTP Server

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public IList<ERPStore.NewsLetters.Models.SMTPSettings> GetSMTPServerList()
		{
			var list = NewsLetterService.GetSMTPServerList();
			if (list == null)
			{
				list = new List<ERPStore.NewsLetters.Models.SMTPSettings>();
			}
			return list;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public ERPStore.NewsLetters.Models.SMTPSettings CreateSMTPServer()
		{
			var result = NewsLetterService.CreateSMTPServer();

			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPost]
		public IList<ERPStore.Models.BrokenRule> ValidateSMTPServer(ERPStore.NewsLetters.Models.SMTPSettings model)
		{
			var result = NewsLetterService.ValidateSMTPServer(model);

			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPut]
		[System.Web.Http.HttpPost]
		public ERPStore.NewsLetters.Models.SMTPSettings SaveSMTPServer(ERPStore.NewsLetters.Models.SMTPSettings model)
		{
			NewsLetterService.SaveSMTPServer(model);
			return model;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpDelete]
		public bool DeleteSMTPServer(ERPStore.NewsLetters.Models.SMTPSettings model)
		{
			if (model.Id == 0)
			{
				return false;
			}
			NewsLetterService.DeleteSMTPServer(model.Id);
			return true;
		}

		#endregion

		#region EmailListSource

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public ERPStore.NewsLetters.Models.EmailListSource CreateEmailListSource(string id)
		{
			var result = NewsLetterService.CreateEmailListSource(id);
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public IDictionary<string, string> GetEmailListSourceTypeDictionary()
		{
			var list = NewsLetterService.GetEmailListSourceTypeList();
			return list;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public IList<ERPStore.NewsLetters.Models.EmailListSource> GetEmailListSourceList()
		{
			var list = NewsLetterService.GetEmailListSourceList();
			return list;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public IDictionary<int, string> GetEmailListSourceDictionary()
		{
			var list = NewsLetterService.GetEmailListSourceDictionary();
			return list;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPost]
		public IList<ERPStore.Models.BrokenRule> ValidateEmailListSouce(ERPStore.NewsLetters.Models.EmailListSource model)
		{
			var result = NewsLetterService.ValidateEmailListSource(model);
			return result;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPost]
		[System.Web.Http.HttpPut]
		public ERPStore.NewsLetters.Models.EmailListSource SaveEmailListSource(ERPStore.NewsLetters.Models.EmailListSource model)
		{
			NewsLetterService.SaveEmailListSource(model);
			return model;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpDelete]
		public bool DeleteEmailListSouce(int id)
		{
			if (id == 0)
			{
				return false;
			}
			NewsLetterService.DeleteEmailListSource(id);
			return true;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public ERPStore.NewsLetters.Models.EmailListSource GetEmailListSourceById(int id)
		{
			var result = NewsLetterService.GetEmailListSourceById(id);
			return result;
		}

		#endregion

		[System.Web.Http.HttpGet]
		[System.Web.Http.HttpPost]
		public bool Subscribe(string email, string visitorId)
		{
			if (email == null
				|| !ERPStore.Validators.EmailValidator.IsValidEmail(email))
			{
				return false;
			}

			var registration = AccountService.GetRegistrationUser(visitorId)
								?? AccountService.GetRegistrationUserByEmail(email);

			if (registration != null
				&& registration.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase))
			{
				// Déjà en base , pas grave
				return true;
			}

			registration = AccountService.CreateRegistrationUser();
			registration.Email = email;
			AccountService.SaveRegistrationUser(visitorId, registration);

			return true;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpGet]
		public string ForceSendPendingItems()
		{
			var workItemId = NewsLetterService.ForceSendPendingItems();
			return workItemId;
		}

		[ERPStore.Web.Controllers.ActionFilters.ApiAuthorizedOperation]
		[System.Web.Http.HttpPost]
		public bool AppendEmailRecipientListToEmailListSource(int id, IEnumerable<ERPStore.NewsLetters.Models.EmailRecipient> list)
		{
			var emailListSource = NewsLetterService.GetEmailListSourceById(id);
			if (emailListSource == null)
			{
				throw new ArgumentException(string.Format("This email source list {0} does not exists", id));
			}

			NewsLetterService.AppendEmailRecipientListToEmailListSource(id, list);
			return true;
		}

	}
}